#pragma once

#include "noncopyable.h"
#include "timestamp.h"

#include <functional>
#include <memory>
/*
理解 EventLoop Channel Poller关系 参考 Reactor模型
Channel通道 包含了socketfd ,以及感兴趣的事件，比如EPOLLIN,EPOLLOUT
POLLER的回调事件
*/
class EventLoop;
class Timestamp;

class Channel : noncopyable {
  public:
    using EventCallback = std::function<void()>;
    using ReadEventCallback = std::function<void(Timestamp)>;
    Channel(EventLoop *loop, int fd);
    ~Channel();

    // fd获得事件后处理
    void handle_event(Timestamp receive_stamp);
    // 设置回调函数对象
    void set_read_callback(ReadEventCallback cb) { read_callback_ = std::move(cb); }
    void set_write_callback(EventCallback cb) { write_callback_ = std::move(cb); }
    void set_close_callback(EventCallback cb) { close_callback_ = std::move(cb); }
    void set_error_callback(EventCallback cb) { error_callback_ = std::move(cb); }
    // 防止channel被手动remove掉，channel还在执行回调操作
    void tie(const std::shared_ptr<void> &);

    int fd() const { return fd_; }
    int events() const { return events_; }
    void set_revents(int revt) { revents_ = revt; }

    // 设置fd相关事件状态
    void enable_reading() {
        events_ |= kReadEvent;
        update();
    }
    void disable_reading() {
        events_ &= ~kReadEvent;
        update();
    }
    void enable_writing() {
        events_ |= kWriteEvent;
        update();
    }
    void disable_writing() {
        events_ &= ~kWriteEvent;
        update();
    }
    void disable_all() {
        events_ = kNoneEvent;
        update();
    }

    // 返回fd当前事件
    bool is_none_event() const { return events_ == kNoneEvent; }
    bool is_reading() const { return events_ & kReadEvent; }
    bool is_writing() const { return events_ & kWriteEvent; }

    int index() const { return index_; }
    void set_index(int idx) { index_ = idx; }
    // one loop per thread
    EventLoop *owner_loop() const { return loop_; }
    void remove();

  private:
    void update();
    void handle_event_with_guard(Timestamp receive_time);

    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop *loop_; // 事件循环
    const int fd_;    // fd,Poller监听的对象
    int events_;      // 注册fd感兴趣的事件
    int revents_;     // poller返回的具体发生的事件
    int index_;

    std::weak_ptr<void> tie_;
    bool tied_;

    // 因为Channel通道里面能够获知fd最终发生的具体的事件revents,用对应的事件
    ReadEventCallback read_callback_;
    EventCallback write_callback_;
    EventCallback close_callback_;
    EventCallback error_callback_;
};
